
import os, sys, cv2, traceback
import numpy as np
parent_path = os.path.abspath(os.path.join(__file__, *(['..'] * 3)))
sys.path.insert(0, parent_path)

import time,threading, yaml
from flask import Flask, request
from gevent import pywsgi

from core.task.task_pipeline import TaskPipeline

from core.utils.logger import logging
from core.server.modules.tcp_server import TcpSteamPush

app = Flask(__name__)

class Server():
    """标准的服务器对象, 根据配置文件可以保存多个pipeline, 并且根据需求进行切换"""
    
    def __init__(self, server_cfg_path) -> None:
        with open(server_cfg_path) as f:
            cfgs = yaml.safe_load(f)
            self._cfgs = cfgs
        self.task_pipeline = TaskPipeline(cfg=cfgs["TaskPipelines"]["ocr"]["path"])
    
    def ocr_predict(self,data):
        self.task_pipeline.task_add(data)
        self.tcp_pusher.rtmp_init(data["pull_url"],data["push_url"])
        self.tcp_pusher.start()
        self.task_pipeline.task_start(data)
        return 200
    
    def task_close(self,data):
        self.task_pipeline.task_pop(data)
        self.tcp_pusher.close()
        return 200



# ------ 系统相关api ------
def restart():
    try:
        logging.info("|restart server...|")
        time.sleep(5)
        shell_file_path = os.path.dirname(__file__)+"/crontab_run.sh"
        os.popen("sh {}".format(shell_file_path))
    except Exception as e:
        logging.error(traceback.format_exc())

@app.route("/sys/restart",methods=["get"])
def handle_restart():
    try:
        logging.info("|/restart|")
        thread_1 = threading.Thread(target = restart)
        thread_1.start()
        return {"code":200}
    except Exception as e:
        logging.error(traceback.format_exc())

@app.route("/sys/change_server_mode",methods=["post"])
def change_server_mode():
    """
    json_data:{
        "mode": [mul/single]
    }
    """
    try:
        json_data  = request.json
        logging.info("|change server mode to {}|".format(json_data["mode"]))
        message = server.change_server_mode(json_data["mode"])
        return {"code":message}
    except Exception as e:
        logging.error(traceback.format_exc())

@app.route("/sys/add_pipeline",methods=["post"])
def add_pipeline():
    """
    json_data:{
        "pipeline_tag": str
    }
    """
    try:
        json_data  = request.json
        logging.info("|add pipeline {}|".format(json_data["pipeline_tag"]))
        message = server.add_standby_pipeline(json_data["pipeline_tag"])
        return {"message":message}
    except Exception as e:
        logging.error(traceback.format_exc())

@app.route("/sys/change_pipeline",methods=["post"])
def change_pipeline():
    """
    json_data:{
        "post_pipeline_tag": str,
        "org_pipeline_tag": str,
    }
    """
    try:
        json_data  = request.json
        logging.info("|change pipeline {} to pipeline {}|".format(json_data["org_pipeline_tag"], json_data["post_pipeline_tag"]))
        message = server.change_standby_pipeline(json_data["org_pipeline_tag"],)
        return {"message":message}
    except Exception as e:
        logging.error(traceback.format_exc())

# ------ 功能api ------

@app.route("/detect",methods=["post"])
def handle_detect():
    """
    json_data: {
        id: int
        mode: [array/b64/file/ftp]
        image: 根据mode的不同存放不同的数据, 比如b64二进制流或文件路径数组
    }
    """
    try:
        logging.info(f"|detect, json data: {request.json}|")
        json_data = request.json
        databox, message = server.predict(json_data, pipeline_tag="base")
        response = {"message":message}
        return response
    except Exception as e:
        logging.error(traceback.format_exc())

@app.route("/rtmp_steam",methods=["post"])
def handle_rtmp_steam():
    """
    json_data = {
        "task_id": 1,
        "task_tag": "RTMP",
        "pull_url": "rtmp://218.94.155.86:1936/live/livestream_74_1",
        "tcp_push_url":"127.0.0.1:2692", # 写死
        "push_url": "rtmp://218.94.155.86:1936/live/livestream_74_3",
        "predict_fps": 1,
        }
    """
    try:
        logging.info(f"|rtmp_steam, json data: {request.json}|")
        json_data = request.json
        message = server.ocr_predict(json_data)

    except Exception as e:
        message = traceback.format_exc()
        logging.error(message)
    return {"message": message}

@app.route("/rtmp_stop",methods=["post"])
def handle_rtmp_stop():
    """
    json_data = {
        "task_id":1,
        }
    """
    try:
        logging.info(f"|rtmp_stop, json data: {request.json}|")
        json_data = request.json
        message = server.task_close(json_data)
        
    except:
        message = traceback.format_exc()
        logging.error(message)
    return {"message": message}

if __name__ == '__main__':
    import multiprocessing as mp
    mp.set_start_method("spawn")

    # 日志初始化
    log_path = "core/utils/logger_samples/log_cfg.yaml"
    logging.set_config(log_path)

    # 定义后台服务类
    server_cfg_path = os.path.dirname(__file__)+"/configs/server_cfg.yml"
    server = Server(server_cfg_path)


    WSGI_server = pywsgi.WSGIServer(('0.0.0.0',2674),app)
    logging.info("|server start|")
    WSGI_server.serve_forever()
    logging.info("|server stop|")

    # app.run(host='0.0.0.0', port=2675)
